package com.tan.chowder.login.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tan.chowder.bean.Result;
import com.tan.chowder.login.bean.User;
import com.tan.chowder.login.entity.SysUserDO;
import com.tan.chowder.login.mapper.SysUserMapper;
import com.tan.chowder.login.service.SysRoleService;
import com.tan.chowder.login.service.SysUserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.Optional;
import java.util.Set;

/**
 * 需要去实现 UserDetails
 * @see org.springframework.security.core.userdetails.UserDetails
 * @author chenx
 *
 *
 */
@Slf4j
@Service
@Transactional
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserDO> implements Serializable,SysUserService {

    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private JwtServiceImpl jwtServiceImpl;

    @Resource
    private SysRoleService sysRoleService;
    @Resource
    AuthenticationManager authenticationManager;

    //
    @Resource
    private BCryptPasswordEncoder passwordEncoder;
//    private SysUserDO user;

    @Override
    public Optional<User> getUserByUsername(String username) {
        User user = this.getBaseMapper().getUserByUsername(username);
        return Optional.of(user);
    }

    @Override
    public Result login(String username, String password) {
        System.out.println("=== login ===" );
        User user = getUserByUsername(username).get();
        String token = null;
        //验证密码是否正确
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(username,password);
        try {
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if(authenticate==null){
                throw new RuntimeException("用户名或密码错误");
            }
            token = jwtServiceImpl.generateToken(user);
            System.out.println("token = " + token);
            String refreshToken = jwtServiceImpl.generateRefreshToken(token);
            System.out.println("refreshToken = " + refreshToken);
        }catch (Exception e){
            log.error("用户名或密码错误!",e);
            throw new RuntimeException("用户名或密码错误");
        }
        return Result.success().ok(token);
    }

    @Override
    public void logout(String token) {
        // 解析Jwt中的用户id
        String username = jwtServiceImpl.getUsernameFromToken(token);
        //删除redis中存储的用户数据
        redisTemplate.delete(username+"");
    }

    /**
     * 移除所有当前人的令牌
     * 结合自身业务场景使用：有些场景是允许同一个账号多设备使用
     * @param user
     */
    private void revokeAllUserTokens(User user) {
        // 获取所有用户的token
        Set<String> tokens = redisTemplate.keys(user.getUsername() + "::");
        if (tokens.isEmpty()) {
            return;
        }
        // 移除所有用户的token
        redisTemplate.delete(tokens);
    }


}